home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 260_01 / zm.c < prev    next >
Text File  |  1988-02-23  |  16KB  |  730 lines

  1. /*
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    01-15-87  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * Entry point Functions:
  7.  *      zsbhdr(type, hdr) send binary header
  8.  *      zshhdr(type, hdr) send hex header
  9.  *      zgethdr(hdr, eflag) receive header - binary or hex
  10.  *      zsdata(buf, len, frameend) send data
  11.  *      zrdata(buf, len) receive data
  12.  *      stohdr(pos) store position data in Txhdr
  13.  *      long rclhdr(hdr) recover position offset from header
  14.  */
  15. #ifndef CANFDX
  16. #include "zmodem.h"
  17. int Rxtimeout = 100;            /* Tenths of seconds to wait for something */
  18. #endif
  19.  
  20. static char *frametypes[] =
  21.    {
  22.    "Carrier Lost",         /* -3 */
  23.    "TIMEOUT",              /* -2 */
  24.    "ERROR",                /* -1 */
  25. #define FTOFFSET 3
  26.    "ZRQINIT",
  27.    "ZRINIT",
  28.    "ZSINIT",
  29.    "ZACK",
  30.    "ZFILE",
  31.    "ZSKIP",
  32.    "ZNAK",
  33.    "ZABORT",
  34.    "ZFIN",
  35.    "ZRPOS",
  36.    "ZDATA",
  37.    "ZEOF",
  38.    "ZFERR",
  39.    "ZCRC",
  40.    "ZCHALLENGE",
  41.    "ZCOMPL",
  42.    "ZCAN",
  43.    "ZFREECNT",
  44.    "ZCOMMAND",
  45.    "ZSTDERR",
  46.    "xxxxx"
  47. #define FRTYPES 22      /* Total number of frame types in this array */
  48.                         /*  not including psuedo negative entries */
  49.    };
  50.  
  51. /* Send ZMODEM binary header hdr of type type */
  52. zsbhdr(type, hdr)
  53. char *hdr;
  54.    {
  55.    int n;
  56.    unsigned short crc;
  57.    
  58.    vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  59.    if (type == ZDATA)
  60.       for (n = Znulls; --n >= 0; )
  61.          zsendline(0);
  62.  
  63.    xsendline(ZPAD);
  64.    xsendline(ZDLE);
  65.  
  66.    if (Txfcs32)
  67.       zsbh32(hdr, type);
  68.    else
  69.       {
  70.       xsendline(ZBIN);
  71.       zsendline(type);
  72.       crc = updcrc(type, 0);
  73.  
  74.       for (n = 4; --n >= 0; )
  75.          {
  76.          zsendline(*hdr);
  77.          crc = updcrc((0377& *hdr++), crc);
  78.          }
  79.       crc = updcrc(0,updcrc(0,crc));
  80.       zsendline(crc>>8);
  81.       zsendline(crc);
  82.       }
  83.    if (type != ZDATA)
  84.       flushmo();
  85.    }
  86.  
  87.  
  88. /* Send ZMODEM binary header hdr of type type */
  89. zsbh32(hdr, type)
  90. char *hdr;
  91.    {
  92.    int n;
  93.    unsigned long crc;
  94.  
  95.    xsendline(ZBIN32);
  96.    zsendline(type);
  97.    crc = UPDC32(type, 0xFFFFFFFF);
  98.  
  99.    for (n = 4; --n >= 0; )
  100.       {
  101.       zsendline(*hdr);
  102.       crc = UPDC32((0377& *hdr++), crc);
  103.       }
  104.    crc = ~crc;
  105.    for (n = 4; --n >= 0;)
  106.       {
  107.       zsendline(crc);
  108.       crc >>= 8;
  109.       }
  110.    }
  111.  
  112. /* Send ZMODEM HEX header hdr of type type */
  113. zshhdr(type, hdr)
  114. char *hdr;
  115.    {
  116.    int n;
  117.    unsigned short crc;
  118.  
  119.    vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  120.    sendline(ZPAD);
  121.    sendline(ZPAD);
  122.    sendline(ZDLE);
  123.    sendline(ZHEX);
  124.    zputhex(type);
  125.  
  126.    crc = updcrc(type, 0);
  127.    for (n = 4; --n >= 0; )
  128.       {
  129.       zputhex(*hdr);
  130.       crc = updcrc((0377& *hdr++), crc);
  131.       }
  132.    crc = updcrc(0,updcrc(0,crc));
  133.    zputhex(crc>>8);
  134.    zputhex(crc);
  135.  
  136.    /* Make it printable on remote machine */
  137.    sendline(015);
  138.    sendline(012);
  139.    /*
  140.     * Uncork the remote in case a fake XOFF has stopped data flow
  141.     */
  142.    if (type != ZFIN)
  143.       sendline(021);
  144.    flushmo();
  145.    }  
  146.  
  147. /*
  148. * Send binary array buf of length length, with ending ZDLE sequence frameend
  149. */
  150. zsdata(buf, length, frameend)
  151. char *buf;
  152.    {
  153.    unsigned short crc;
  154.  
  155.    vfile("zsdata: length=%d end=%x", length, frameend);
  156.    if (Txfcs32)
  157.       zsda32(buf, length, frameend);
  158.    else
  159.       {
  160.       crc = 0;
  161.       for ( ; --length >= 0; )
  162.          {
  163.          zsendline(*buf);
  164.          crc = updcrc((0377& *buf++), crc);
  165.          }
  166.       xsendline(ZDLE);
  167.       xsendline(frameend);
  168.       crc = updcrc(frameend, crc);
  169.  
  170.       crc = updcrc(0,updcrc(0,crc));
  171.       zsendline(crc>>8);
  172.       zsendline(crc);
  173.       }
  174.    if (frameend == ZCRCW)
  175.       {
  176.       xsendline(XON);
  177.       flushmo();
  178.       }
  179.    }
  180.  
  181. zsda32(buf, length, frameend)
  182. char *buf;
  183.    {
  184.    unsigned long crc;
  185.  
  186.    crc = 0xFFFFFFFF;
  187.    for ( ;--length >= 0; )
  188.       {
  189.       zsendline(*buf);
  190.       crc = UPDC32((0377& *buf++), crc);
  191.       }
  192.    xsendline(ZDLE);
  193.    xsendline(frameend);
  194.    crc = UPDC32(frameend, crc);
  195.  
  196.    crc = ~crc;
  197.    for (length = 4; --length >= 0; )
  198.       {
  199.       zsendline(crc);
  200.       crc >>= 8;
  201.       }
  202.    }
  203.  
  204. /*
  205.  * Receive array buf of max length with ending ZDLE sequence
  206.  *  and CRC.  Returns the ending character or error code.
  207.  */
  208. zrdata(buf, length)
  209. char *buf;
  210.    {
  211.    int c;
  212.    unsigned short crc;
  213.    int d;
  214.  
  215.    if (Rxframeind == ZBIN32)
  216.       return(zrdat32(buf, length));
  217.  
  218.    crc = Rxcount = 0;
  219.    for (;;)
  220.       {
  221.       if ((c = zdlread()) & ~0377)
  222.          {
  223. crcfoo:
  224.          switch (c)
  225.             {
  226.             case GOTCRCE:
  227.             case GOTCRCG:
  228.             case GOTCRCQ:
  229.             case GOTCRCW:
  230.                crc = updcrc((d=c)&0377, crc);
  231.                if ((c = zdlread()) & ~0377)
  232.                   goto crcfoo;
  233.                crc = updcrc(c, crc);
  234.                if ((c = zdlread()) & ~0377)
  235.                   goto crcfoo;
  236.                crc = updcrc(c, crc);
  237.                if (crc & 0xFFFF)
  238.                   {
  239.                   zperr("Bad data CRC %x", crc);
  240.                   return(ERROR);
  241.                   }
  242.                vfile("zrdata: cnt = %d ret = %x", Rxcount, d);
  243.                return(d);
  244.             case GOTCAN:
  245.                zperr("ZMODEM: Sender Canceled");
  246.                return(ZCAN);
  247.             case TIMEOUT:
  248.                zperr("ZMODEM data TIMEOUT");
  249.                return(c);
  250.             default:
  251.                zperr("ZMODEM bad data subpacket ret=%x", c);
  252.                return(c);
  253.             }
  254.          }
  255.       if (--length < 0)
  256.          {
  257.          zperr("ZMODEM data subpacket too long");
  258.          return(ERROR);
  259.          }
  260.       ++Rxcount;
  261.       *buf++ = c;
  262.       crc = updcrc(c, crc);
  263.       continue;
  264.       }
  265.    }
  266.  
  267. zrdat32(buf, length)
  268. char *buf;
  269.    {
  270.    int c;
  271.    unsigned long crc;
  272.    int d;
  273.  
  274.    crc = 0xFFFFFFFF;
  275.    Rxcount = 0;
  276.    for (;;)
  277.       {
  278.       if ((c = zdlread()) & ~0377)
  279.          {
  280. crcfoo:
  281.          switch (c)
  282.             {
  283.             case GOTCRCE:
  284.             case GOTCRCG:
  285.             case GOTCRCQ:
  286.             case GOTCRCW:
  287.                crc = UPDC32((d=c)&0377, crc);
  288.                if ((c = zdlread()) & ~0377)
  289.                   goto crcfoo;
  290.                crc = UPDC32(c, crc);
  291.                if ((c = zdlread()) & ~0377)
  292.                   goto crcfoo;
  293.                crc = UPDC32(c, crc);
  294.                if ((c = zdlread()) & ~0377)
  295.                   goto crcfoo;
  296.                crc = UPDC32(c, crc);
  297.                if ((c = zdlread()) & ~0377)
  298.                   goto crcfoo;
  299.                crc = UPDC32(c, crc);
  300.                if (crc != 0xDEBB20E3)
  301.                   {
  302.                   zperr("Bad data CRC %lX", crc);
  303.                   return(ERROR);
  304.                   }
  305.                vfile("zrdat32: cnt = %d ret = %x", Rxcount, d);
  306.                return(d);
  307.             case GOTCAN:
  308.                zperr("ZMODEM: Sender Canceled");
  309.                return(ZCAN);
  310.             case TIMEOUT:
  311.                zperr("ZMODEM data TIMEOUT");
  312.                return(c);
  313.             default:
  314.                zperr("ZMODEM bad data subpacket ret=%x", c);
  315.                return(c);
  316.             }
  317.          }
  318.       if (--length < 0)
  319.          {
  320.          zperr("ZMODEM data subpacket too long");
  321.          return(ERROR);
  322.          }
  323.       ++Rxcount;
  324.       *buf++ = c;
  325.       crc = UPDC32(c, crc);
  326.       continue;
  327.       }
  328.    }
  329.  
  330.  
  331. /*
  332. * Read a ZMODEM header to hdr, either binary or hex.
  333. *  eflag controls local display of non zmodem characters:
  334. *      0:  no display
  335. *      1:  display printing characters only
  336. *      2:  display all non ZMODEM characters
  337. *  On success, set Zmodem to 1 and return type of header.
  338. *   Otherwise return negative on error
  339. */
  340. zgethdr(hdr, eflag)
  341. char *hdr;
  342.    {
  343.    int c, n, cancount;
  344.    
  345.    n = Baudrate;   /* Max characters before start of frame */
  346.    cancount = 5;
  347. again:
  348.    Rxframeind = Rxtype = 0;
  349.    switch (c = noxread7())
  350.       {
  351.       case RCDO:
  352.       case TIMEOUT:
  353.          goto fifi;
  354.       case CAN: